import datetime
import pandas as pd
from absl import app, flags
from sqlalchemy.orm import scoped_session, sessionmaker
from xunkemgmt_client.market.feed_stats_v2.model.feed_stats import FeedStatsIndex
from xunkemgmt_client.market.feed_stats_v2.database.connection.coin2_database import coin2_feed_stats_importer_engine,coin2_feed_stats_querier_engine
from sqlalchemy import MetaData

FLAGS = flags.FLAGS

metadata = MetaData()
metadata.reflect(coin2_feed_stats_querier_engine)
FeedStatsInfo = metadata.tables['FeedStatsInfo']
IntervalStats = metadata.tables['IntervalStats']

machine_list = [
    'feed-01.ap-southeast-1.aws',
    'feed-01.ap-northeast-1.aws.huobi',
    'feed-02.ap-northeast-2.aws',
    'feed-02.eu-west-1.aws',
    'feed-02.us-east-1.aws',
    'feed-05.ap-northeast-1.aws',
    'feed-05.cn-hongkong.aliyun',
    'feed-10.ap-northeast-1.aws',
]


class FeedStatsCleaner():
  def clean_redundant_data(self, trading_date):
    session = self._get_session()
    feed_stats_info = []
    print("start to clean %s" % (trading_date))
    for machine in machine_list:
      machine_feed_stats_info = pd.DataFrame(session.query(FeedStatsInfo).filter(
          FeedStatsInfo.c.machine == machine,
          FeedStatsInfo.c.trading_date == trading_date
      ))
      if not machine_feed_stats_info.empty:
        feed_stats_info.append(machine_feed_stats_info)
    if (len(feed_stats_info) > 0):
      feed_stats_info = pd.concat(feed_stats_info, axis=0)
      feed_stats_info.sort_values(by='create_time', inplace=True)
      hold_feed_stats = feed_stats_info.drop_duplicates(
          ['trading_date', 'machine', 'exchange_api_id', 'symbol', 'native_symbol', 'recipe', 'worker', 'feed_source'], keep='last')
      if len(hold_feed_stats) != len(feed_stats_info):
        remove_feed_stats_id = set(feed_stats_info['feed_stats_id']) - set(hold_feed_stats['feed_stats_id'])
        print(f"remove {len(remove_feed_stats_id)} feed stats ids")
        session.query(FeedStatsIndex).filter(
          FeedStatsIndex.feed_stats_id.in_(remove_feed_stats_id)).delete(synchronize_session="fetch")
        # session.rollback()
        session.commit()
        print('done')
      else:
        print('nothing to clean')
    session.close()
  

  def clean_interval_status(self,holding_days):
    print(f"start to clean interval status, data older than {holding_days} days will be deleted")
    session = self._get_session()
    start_id = session.query(IntervalStats.c.feed_stats_id).first()[0]
    start_date = session.query(FeedStatsInfo.c.trading_date).filter(FeedStatsInfo.c.feed_stats_id == start_id).first()[0]
    current_date = datetime.datetime.utcnow().date()
    remove_days = (current_date-start_date).days - holding_days
    if remove_days > 0:
      new_start_date = start_date + datetime.timedelta(days=remove_days)
      new_start_id = session.query(FeedStatsInfo.c.feed_stats_id).filter(FeedStatsInfo.c.trading_date == new_start_date).first()[0]
      if new_start_id > start_id:
        print(f"remove feed_stats_id from {start_id} to {new_start_id}")
        session.query(IntervalStats).filter(
          IntervalStats.c.feed_stats_id <= new_start_id,
          IntervalStats.c.feed_stats_id >= start_id).delete(synchronize_session=False)
        # session.rollback()
        session.commit()
        print('done')
        session.close()
        return
    print('nothing to clean')
  

  def _get_session(self):
    return scoped_session(sessionmaker(autocommit=False,
                                       autoflush=False,
                                       bind=coin2_feed_stats_importer_engine))

def main(_):
  if FLAGS.start_date is None:
    print('need to specific a start date to run')
    return
  end_date = FLAGS.end_date or FLAGS.start_date
  if FLAGS.start_date > end_date :
    print('start date must less than end date')
    return
  cleaner = FeedStatsCleaner()
  start_date = datetime.datetime.strptime(FLAGS.start_date, '%Y%m%d')
  end_date = datetime.datetime.strptime(end_date, '%Y%m%d')

  while(start_date<=end_date):
    cleaner.clean_redundant_data(start_date.date())
    start_date = start_date + datetime.timedelta(days=1)
  if FLAGS.interval_feed_retention.isnumeric():
    holding_days = int(FLAGS.interval_feed_retention)
    holding_days = max(holding_days,90)
    cleaner.clean_interval_status(holding_days)
  
  
if __name__ == '__main__':
  flags.DEFINE_string('start_date', None, 'start trading date,yyyymmdd')
  flags.DEFINE_string('end_date', 'None', 'end trading date yyyymmdd')
  flags.DEFINE_string('interval_feed_retention', None, 'interval feed retention days')
  app.run(main)
